#include "MysqlConn.hpp"

// 初始化数据库连接
MysqlConn::MysqlConn() {
    m_conn = mysql_init(nullptr);
    // 设置编码模式
    mysql_set_character_set(m_conn, "utf8");
}

// 释放数据库连接
MysqlConn::~MysqlConn() {
    if (m_conn != nullptr) {
        mysql_close(m_conn);
    }
    freeAns(); 
}

// 连接数据库
bool MysqlConn::connect(string user, string passwd, string dbName, string ip, size_t port) {
    MYSQL* ptr = mysql_real_connect(m_conn, ip.c_str(), user.c_str(), passwd.c_str(), dbName.c_str(), port, nullptr, 0);
    return ptr != nullptr;
}

// 更新数据库： insert, update, delete
bool MysqlConn::update(string sql) {
    // 原代码逻辑有误，已修正
    return mysql_query(m_conn, sql.c_str()) == 0;
}

// 查询数据库
bool MysqlConn::query(string sql) {
    freeAns();
    // select 语句
    if (mysql_query(m_conn, sql.c_str())) {
        return false;
    }
    m_ans = mysql_store_result(m_conn);
    return true;
}

// 遍历查询得到的结果集
bool MysqlConn::next() {
    if (m_ans != nullptr) {
        m_row = mysql_fetch_row(m_ans);
        if (m_row != nullptr)
            return true;
    }
    return false;
}

// 得到结果集中的字段值
string MysqlConn::value(int index) {
    int rowCount = mysql_num_fields(m_ans);
    if (index >= rowCount || index < 0) {
        return "";
    }
    char* val = m_row[index];
    // 注意 /0 情况
    size_t length =  mysql_fetch_lengths(m_ans)[index];
    // 将 length 长度 的 char* 字符转化成字符串 就避免了 遇见/0读取不完整的情况
    return string(val, length);
}

// 事务操作
bool MysqlConn::transaction() {
    return mysql_autocommit(m_conn, false);    // 手动提交
}

// 提交事务
bool MysqlConn::commit() {
    return mysql_commit(m_conn);
}

// 事务回滚
bool MysqlConn::rollback() {
    return mysql_rollback(m_conn);
}

// 私有
void MysqlConn::freeAns() {
    if (m_ans) {
        mysql_free_result(m_ans);
        m_ans = nullptr;
    }
}

// 刷新起始的空闲时间点
void MysqlConn::refreshAliveTime() {
    // 某个数据库起始时间点
    m_alivetime = steady_clock::now();
}

// 计算连接存活总时长
long long MysqlConn::getAliveTime() {
    nanoseconds ans = steady_clock::now() - m_alivetime;
    milliseconds millisec = duration_cast<milliseconds>(ans);    // 损失精度
    return millisec.count();
}